package com.yenlien.traceyun.produce.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yenlien.traceyun.business.dao.ProcessDetailDao;
import com.yenlien.traceyun.business.dao.ProduceManageDao;
import com.yenlien.traceyun.business.dao.ProduceManageTechDao;
import com.yenlien.traceyun.business.entity.ProcessDetail;
import com.yenlien.traceyun.business.entity.ProduceManage;
import com.yenlien.traceyun.business.entity.ProduceManageTech;
import com.yenlien.traceyun.business.service.rest.usercenter.FileRestService;
import com.yenlien.traceyun.common.utils.Tools;
import com.yenlien.traceyun.webase.exception.BusinessException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

/**
 * 生产管理
 */
@Service
public class ManageService {
    @Autowired
    private ProduceManageDao produceManageDao;
    @Autowired
    private ProcessDetailDao processDetailDao;
    @Autowired
    private ProduceManageTechDao produceManageTechDao;
    @Autowired
    private FileRestService fileService;


    /**
     * 添加生产管理
     *
     * @param producemanage
     */
//    @Transactional
//    public ProduceManage save(ProduceManage producemanage) {
////        ProduceManage save = produceManageDao.save(producemanage);
////        ProcessDetail processDetail = new ProcessDetail();
////        processDetail.setProcessId(save.getId());
////        processDetail.setTechnologyId(save.getTechnologyId());
////        processDetail.setProductName(save.getManageName());
////        processDetail.setTotalNumber(save.getPredictYield());
////        processDetail.setType(save.getType());
////        processDetail.setIsCheck(0);
////        processDetailDao.save(processDetail);
//        return produceManageDao.save(producemanage);
//    }
    @Transactional
    public ProduceManage save(ProduceManage producemanage, List<MultipartFile> files) {
        List<ProcessDetail> processDetailList = JSONArray.parseArray(producemanage.getProcessDetailList(), ProcessDetail.class);
        Double all = processDetailList.stream().map(ProcessDetail::getTotalNumber).map(Double::valueOf).reduce(Double::sum).get();

        String subtr = Tools.subtr(producemanage.getPredictYield(), all.toString());
        if (new BigDecimal(subtr).compareTo(new BigDecimal("0")) == -1) {
            throw new BusinessException("数量不能大于预计产量");
        }

        ProduceManage save = produceManageDao.save(producemanage);
        List<ProduceManageTech> produceManageTechList = JSONArray.parseArray(producemanage.getProduceManageTechList(), ProduceManageTech.class);
        // 匹配图片名  文件名一样会存在问题 FileNotFoundException 或者 第二个对象的file字段没有赋上值，第一个file会被赋值两次
        for (ProduceManageTech tech : produceManageTechList) {
            for (MultipartFile file : files) {
                String name = file.getOriginalFilename();
                // 前端把文件名也携带上然后匹配文件名
                if (name.equals(tech.getOperaImg())) {
                    tech.setOperaImg(fileService.upload(file));
                    tech.setProduceManageId(save.getId());
                    break;
                }
            }
        }
        produceManageTechDao.saveAll(produceManageTechList);

        for (ProcessDetail processDetail : processDetailList) {
            processDetail.setProcessId(save.getId());
            processDetail.setSurplusNumber(processDetail.getTotalNumber());
        }
//        List<ProcessDetail> procDetails = processDetailDao.findByProcessId(save.getId());
        // 把单位统一转成 g
//        if("kg".equals(produceManage.getMonad())){
//            produceManage.setPredictYield(Tools.multiply(produceManage.getPredictYield(), new BigDecimal("1000").toString()));
//        }
//        Double all = Stream.concat(procDetails.stream(), processDetailList.stream()).map(x -> {
//            if("kg".equals(x.getUnits())){
//                return Tools.multiply(x.getTotalNumber(), new BigDecimal("1000").toString());
//            }
//            return x.getTotalNumber();
//        }).map(Double::valueOf).reduce(Double::sum).get();


        // 数量不能大于 predictYield 预计产量
//        Double all = Stream.concat(procDetails.stream(), processDetailList.stream()).map(ProcessDetail::getTotalNumber).map(Double::valueOf).reduce(Double::sum).get();
        processDetailDao.saveAll(processDetailList);
        return save;
    }


    public List<ProduceManageTech> saveTech(List<ProduceManageTech> produceManageTechList, List<MultipartFile> files) {
        // 匹配图片名
        for (MultipartFile file : files) {
            String name = file.getName();
            for (ProduceManageTech tech : produceManageTechList) {
                // 前端把文件名也携带上然后匹配文件名
                if (name.equals(tech.getOperaImg())) {
                    tech.setOperaImg(fileService.upload(files));
                    break;
                }
            }
        }
        return produceManageTechDao.saveAll(produceManageTechList);
    }


    public List<ProcessDetail> saveProc(List<ProcessDetail> processDetailList) {
        String processId = processDetailList.get(0).getProcessId();
        List<ProcessDetail> procDetails = processDetailDao.findByProcessId(processId);
        ProduceManage produceManage = produceManageDao.findById(processId);
        // 数量不能大于 predictYield 预计产量
        Double all = Stream.concat(procDetails.stream(), processDetailList.stream()).map(ProcessDetail::getTotalNumber).map(Double::valueOf).reduce(Double::sum).get();
        String subtr = Tools.subtr(produceManage.getPredictYield(), all.toString());
        if (new BigDecimal(subtr).compareTo(new BigDecimal("0")) == -1) {
            throw new BusinessException("数量不能大于预计产量");
        }
        return processDetailDao.saveAll(processDetailList);
    }

    /**
     * 查询生产管理
     *
     * @param page
     * @return
     */
    public Page<ProduceManage> select(Integer page, String type) {
        Sort ageSort = Sort.by(Sort.Direction.DESC, "createtime");
        PageRequest pageRequest = PageRequest.of(page, 10, ageSort);
        Page<ProduceManage> byType;
        if (StringUtils.isNotBlank(type)) {
            byType = produceManageDao.findByType(type, pageRequest);
        } else {
            byType = produceManageDao.findAll(pageRequest);
        }
        List<ProduceManage> content = byType.getContent();
        for (ProduceManage produceManage : content) {
            produceManage.setProcessDetailList(JSONObject.toJSONString(processDetailDao.findByProcessId(produceManage.getId())));
            produceManage.setProduceManageTechList(JSONObject.toJSONString(produceManageTechDao.findByProduceManageId(produceManage.getId())));
        }
        return new PageImpl<>(content, pageRequest, byType.getTotalElements());
    }

    public Page<ProcessDetail> getProcessDetail(Integer page, String type, String companyId, String searchName) {
        PageRequest pageRequest = PageRequest.of(page, 10, Sort.by(Sort.Direction.DESC, "createtime"));
//        Page<ProcessDetail> byType;
//        if (StringUtils.isNotBlank(type)) {
//            byType = processDetailDao.findByTypeAndCompanyId(type, companyId, pageRequest);
//        } else {
//            byType = processDetailDao.findByCompanyId(companyId, pageRequest);
//        }
//        return byType;
        return processDetailDao.findAll((Root<ProcessDetail> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
            List<Predicate> list_or = new ArrayList<>();
            List<Predicate> list_and = new ArrayList<>();
            list_and.add(cb.equal(root.get("companyId"), companyId));
            if(StringUtils.isNotBlank(type)){
                list_and.add(cb.equal(root.get("type"), type));
            }
            Predicate pre_and = cb.and(list_and.toArray(new Predicate[list_and.size()]));
            if (StringUtils.isNotBlank(searchName)) {
                list_or.add(cb.like(root.get("productName"), "%" + searchName + "%"));
                list_or.add(cb.like(root.get("batch"), "%" + searchName + "%"));
            }else {
                return pre_and;
            }
            Predicate pre_or = cb.or(list_or.toArray(new Predicate[list_or.size()]));
            return query.where(pre_and, pre_or).getRestriction();
        }, pageRequest);
    }


    /**
     * 搜索栏
     * @param searchName
     * @return
     */
    public Page<ProduceManage> searchPage(Integer page, String searchName, String type, String companyId) {
        PageRequest pageRequest = PageRequest.of(page > 0 ? page - 1 : page, 10, Sort.by(Sort.Direction.DESC, "createtime"));
        return produceManageDao.findAll((Root<ProduceManage> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
            List<Predicate> list_or = new ArrayList<>();
            List<Predicate> list_and = new ArrayList<>();
            list_and.add(cb.equal(root.get("companyId"), companyId));
            if(StringUtils.isNotBlank(type)){
                list_and.add(cb.equal(root.get("type"), type));
            }
            Predicate pre_and = cb.and(list_and.toArray(new Predicate[list_and.size()]));
            if (StringUtils.isNotBlank(searchName)) {
                list_or.add(cb.like(root.get("batch"), "%" + searchName + "%"));
                list_or.add(cb.like(root.get("manageName"), "%" + searchName + "%"));
            }else {
                return pre_and;
            }
            Predicate pre_or = cb.or(list_or.toArray(new Predicate[list_or.size()]));
            return query.where(pre_and, pre_or).getRestriction();
        }, pageRequest);
    }

    /**
     * 根据id查询生产管理
     *
     * @param id
     * @return
     */
    public Object selectId(String id) {
        ProduceManage byId = produceManageDao.findById(id);
        return byId;
    }

    /**
     * 根据id修改生产管理
     *
     * @param produceManage
     * @return
     */
    @Transactional
    public void update(ProduceManage produceManage) {
        if (produceManage.getId() != null) {
            produceManageDao.save(produceManage);
        } else {
            throw new BusinessException("500", "修改失败");
        }
    }

    /**
     * 根据id删除生产信息
     *
     * @param produceManage
     */
    @Transactional
    public void delete(ProduceManage produceManage) {
        if (produceManage.getId() != null) {
            produceManageDao.delete(produceManage);
            List<ProcessDetail> byProcessId = processDetailDao.findByProcessId(produceManage.getId());
            processDetailDao.deleteAll(byProcessId);
        } else {
            throw new BusinessException("500", "删除错误，不存在该生产信息");
        }
    }
}
